#pragma once

#include "noncopyable.h"
#include <functional>
#include <memory>
#include"Timestamp.h"
class Timestamp;
class EventLoop;

/**
 * EventLoop 当中管理大量的 Channel
 * Channel 理解为通道，封装了sockfd和对应的事件； 可以理解为就绪节点
 */

class Channel : noncopyable
{
public:
    // 定义一个名字，这个名字的类型是后面的这个，两种写法效果相同
    // typedef std::function<void()> EventCallBack;
    using EventCallBack = std::function<void()>;
    using ReadEventCallBack = std::function<void(Timestamp)>;

    Channel(EventLoop *loop, int fd);
    ~Channel();

    // fd 得到poller通知以后，处理事件的入口. 即回调相应的方法
    void handlerEvent(Timestamp receiveTime);

    // 设置回调函数对象
    void setReadCallback(ReadEventCallBack cb) { readCallback_ = std::move(cb); }
    void setWriteCallback(EventCallBack cb) { writeCallback_ = std::move(cb); }
    void setCloseCallback(EventCallBack cb){closeCallback_ = std::move(cb);}
    void setErrorCallback(EventCallBack cb){errorCallback_ = std::move(cb);}

    // 防止当channel 被手动remove掉，channel还在执行回调操作
    void tie(const std::shared_ptr<void> &);

    // 返回fd
    int fd() const { return fd_; }

    int events() const { return events_; }
    // 为什么设置这里的revent? 而不是通过epoll进行监听然后设置呢?
    int set_revents(int revt) { revents_ = revt; return revents_;}
    //bool isNoneEvent() const { return events_ == kNoneEvent; }

    // 让该节点去关心读事件
    void enableReading()
    {
        events_ |= kReadEvent;
        update(); // 调用epoll_ctl 让红黑树关心这个事件
    }

    // 即不关心读事件
    void disableReading() {events_ &= ~kReadEvent; update();}

    void enableWriting()
    {
        events_ |= kWriteEvent;
        update(); // 调用epoll_ctl 让红黑树关心这个事件
    }

    // 即不关心读事件
    void disableWriting() {events_ &= ~kWriteEvent; update();}

    void disableAll(){events_ = kNoneEvent; update();}

    // 返回fd当前的事件状态
    bool isNoneEvent() const {return events_ == kNoneEvent;}
    bool isWriting() const {return events_ & kWriteEvent;}
    bool isReading() const {return events_ & kReadEvent;}

    int index(){ return index_;}
    void set_index(int idx) {index_ = idx;}

    // one loop pre thread
    EventLoop* ownerLoop() {return loop_;}
    void remove();
private:
    void update();
    void handlerEventWithGuard(Timestamp receiverTime);
private:
    static const int kNoneEvent; // 对任何事件都不感兴趣
    static const int kReadEvent; // 对读事件
    static const int kWriteEvent;

    EventLoop *loop_; // 事件循环
    const int fd_;    // fd,Poller 监听的对象, epoll_ctl
    int events_;      // 注册fd 感兴趣的事件
    int revents_;     // poller 返回的具体发生的事件
    int index_;       // 这个是表达当前Channel的状态

    std::weak_ptr<void> tie_;
    bool tied_;

    // Channel 通道能够获知fd最终发生的具体事件revents，所以它负责调用具体事件的回调操作
    // 每一个Channel都代表一个事件节点，这里的定义回调的类型
    ReadEventCallBack readCallback_;// void()
    EventCallBack writeCallback_;   // void(Timestamp);
    EventCallBack closeCallback_;
    EventCallBack errorCallback_;
};